package com.java.app.hacktouch.view

import android.app.Activity
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.os.Handler
import android.os.HandlerThread
import android.util.AttributeSet
import android.util.DisplayMetrics
import android.util.Log
import android.view.MotionEvent
import android.view.View
import com.github.nisrulz.sensey.Sensey
import com.github.nisrulz.sensey.TouchTypeDetector
import com.java.app.hacktouch.mouse.MouseAction
import com.java.app.hacktouch.mouse.MouseParams
import com.java.app.hacktouch.parameter.MotionMode

/**
 * Created by guanguojin on 2017/11/1.
 */

class HackView : View {

    private var mCanvas: Canvas? = null
    private var mBitmapPaint: Paint? = null
    private var mBitmap: Bitmap? = null
    private var mPaint: Paint? = null

    @Volatile private var mX: Float = 0.toFloat()
    @Volatile private var mY: Float = 0.toFloat()
    @Volatile private var mXoffset: Float = 0.toFloat()
    @Volatile private var mYoffset: Float = 0.toFloat()

    private val mMouseParams = MouseParams()
    private var mContext: Context? = null
    private var bitmapWidth: Int = 0
    private var bitmapHeight: Int = 0
    /*
     * 设置手势模式、鼠标模式
     * */
    var mode = MotionMode.MOUSE_MODE
        set(mode) {
            removeAllPaint()
            field = mode
            if (this.mode === MotionMode.MOUSE_MODE) {
                Sensey.getInstance().startTouchTypeDetection(mContext, hackTouchListner)
            } else {
                Sensey.getInstance().stopTouchTypeDetection()
            }
        }
    private var startReport = false

    //dithering
    private val ditherDly = 100
    private var hackTouchType = TouchType.NONE
    private var ditherHandler = Handler()
    private val ditherRunner = Runnable {
        when (hackTouchType) {
            TouchType.SINGLE -> {
                MouseAction.leftOnClick()
                MouseAction.upOnClick()
                hackTouchType = TouchType.NONE
                Log.i(TAG, "left click")
            }
            TouchType.TWO_FINGER -> {
                MouseAction.rightOnClick()
                MouseAction.upOnClick()
                hackTouchType = TouchType.NONE
                Log.i(TAG, "right click")
            }
            TouchType.THREE_FINGER -> {
                MouseAction.leftOnClick()
                Log.i(TAG, "three finger click")
            }
            else -> {
                Log.i(TAG, "none click")
            }
        }
    }

    //polling rate counter
    private var pollingrate = 0
    private val pollingHandler = Handler()
    private val pollingRunnber = object : Runnable {
        override fun run() {
            Log.i(TAG, "PollRate: $pollingrate Hz")
            pollingrate = 0
            pollingHandler.postDelayed(this, 1000)
        }
    }

    //sampling
    private val simpingInterval = 4
    private var simplingThread = HandlerThread("sampling")
    private var simplingInstance :Handler? = null

    private val simplingTask = object : Runnable {
        override fun run() {
            if (startReport == true) {
                var xoffset = mXoffset.toInt()
                var yoffset = mYoffset.toInt()
                var button = 0
                if (hackTouchType === TouchType.THREE_FINGER) {
                    button = MouseParams.leftTap
                }

//                                    pollingrate++;
//                                    MouseAction.movePointer(
//                                            MouseParams.lenght,
//                                            xoffset,
//                                            yoffset,
//                                            mMouseParams.cursorStep,
//                                            button)

                if (Math.abs(xoffset) > mMouseParams.xOffset) {
                    xoffset = IAC(xoffset, mMouseParams.cursorStep)
                } else {
                    xoffset = 0
                }

                if (Math.abs(yoffset) > mMouseParams.yOffset) {
                    yoffset = IAC(yoffset, mMouseParams.cursorStep)
                } else {
                    yoffset = 0
                }

                if (xoffset != 0 || yoffset != 0) {
                    pollingrate++
                    MouseAction.movePointer(
                            MouseParams.lenght,
                            xoffset,
                            yoffset,
                            button)
                }
            }
            simplingInstance!!.postDelayed(this, simpingInterval.toLong())
        }

    }

    //interactive acceleration compensation
    private fun IAC(offset: Int, step: Int): Int {

        val abs_offset = Math.abs(offset)

        return if (abs_offset >= 45) {
            if (step * 3 >= 127) {
                if (offset > 0) 127 else -127
            } else {
                if (offset > 0) step * 3 else -step * 3
            }
        } else if (abs_offset in 35..45) {
            if (offset > 0) step * 2 else -step * 2
        } else if (abs_offset in 25..35) {
            if (offset > 0) step * 3 / 2 else step * -3 / 2
        } else if (abs_offset in 15..25) {
            if (offset > 0) step else -step
        } else if (abs_offset in 5..15) {
            if (offset > 0) step / 2 else -step / 2
        } else if (abs_offset in 0..5) {
            if (offset > 0) 1 else -1
        } else {
            0
        }
    }

    internal var hackTouchListner: TouchTypeDetector.TouchTypListener = object : TouchTypeDetector.TouchTypListener {

        override fun onTwoFingerSingleTap() {

            Log.i(TAG, "onTwoFingerSingleTap")
            hackTouchType = TouchType.TWO_FINGER
            ditherHandler.removeCallbacks(ditherRunner)
            ditherHandler.postDelayed(ditherRunner, ditherDly.toLong())
        }

        override fun onThreeFingerSingleTap() {
            Log.i(TAG, "onThreeFingerSingleTap")
            hackTouchType = TouchType.THREE_FINGER
            ditherHandler.removeCallbacks(ditherRunner)
            ditherHandler.postDelayed(ditherRunner, ditherDly.toLong())
        }

        override fun onDoubleTap() {

        }

        override fun onScroll(i: Int) {

        }

        override fun onSingleTap() {
            Log.i(TAG, "onSingleTap")
            hackTouchType = TouchType.SINGLE
            ditherHandler.removeCallbacks(ditherRunner)
            ditherHandler.postDelayed(ditherRunner, ditherDly.toLong())
        }

        override fun onSwipe(i: Int) {

        }

        override fun onLongPress() {

        }
    }

    private fun startSampling() {
        simplingInstance!!.postDelayed(simplingTask, simpingInterval.toLong())
    }

    private fun stopSampling() {
        simplingInstance!!.removeCallbacks(simplingTask)
    }

    constructor(c: Context) : super(c) {
        mContext = c
        //得到屏幕的分辨率
        val dm = DisplayMetrics()
        (c as Activity).windowManager.defaultDisplay.getMetrics(dm)

        bitmapWidth = dm.widthPixels
        bitmapHeight = dm.heightPixels - 2 * 45

        initCanvas()
        initTouchEvent()
    }

    constructor(c: Context, attrs: AttributeSet) : super(c, attrs) {
        mContext = c
        //得到屏幕的分辨率
        val dm = DisplayMetrics()
        (c as Activity).windowManager.defaultDisplay.getMetrics(dm)

        bitmapWidth = dm.widthPixels
        bitmapHeight = dm.heightPixels - 2 * 45

        initCanvas()
        initTouchEvent()
    }

    //初始化画布
    fun initCanvas() {

        mPaint = Paint()
        mPaint!!.isAntiAlias = true
        mPaint!!.isDither = true
        mPaint!!.color = -0xffff33
        mPaint!!.style = Paint.Style.STROKE
        mPaint!!.strokeJoin = Paint.Join.ROUND
        mPaint!!.strokeCap = Paint.Cap.ROUND
        mPaint!!.strokeWidth = 12f

        mBitmapPaint = Paint(Paint.DITHER_FLAG)

        //画布大小
        mBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
                Bitmap.Config.RGB_565)
        mCanvas = Canvas(mBitmap!!)  //所有mCanvas画的东西都被保存在了mBitmap中

        mCanvas!!.drawColor(Color.WHITE)
        mBitmapPaint = Paint(Paint.DITHER_FLAG)

    }

    private fun initTouchEvent() {
        ditherHandler = Handler()
        simplingThread.start()
        simplingInstance = Handler(simplingThread.looper)

        Sensey.getInstance().init(mContext!!)
        Sensey.getInstance().startTouchTypeDetection(mContext, hackTouchListner)
    }

    override fun dispatchTouchEvent(event: MotionEvent): Boolean {
        // Setup onTouchEvent for detecting type of touch gesture
        Sensey.getInstance().setupDispatchTouchEvent(event)
        return super.dispatchTouchEvent(event)
    }

    override fun onDraw(canvas: Canvas) {
        canvas.drawBitmap(mBitmap!!, 0f, 0f, mBitmapPaint)     //显示旧的画布
    }

    /*
     * 清空的主要思想就是初始化画布
     * 将保存路径的两个List清空
     * */
    fun removeAllPaint() {
        //调用初始化画布函数以清空画布
        initCanvas()
        invalidate()//刷新
    }

    fun setMouseParams(params: MouseParams) {
        mMouseParams.xOffset = params.xOffset
        mMouseParams.yOffset = params.yOffset
        mMouseParams.cursorStep = params.cursorStep
        mMouseParams.circleSize = params.circleSize
    }

    fun startReport() {
        startReport = true
    }

    fun stopReport() {
        startReport = false
    }

    private fun touchPoint(x: Float, y: Float) {
        removeAllPaint()
        mCanvas!!.drawCircle(x, y, mMouseParams.circleSize.toFloat(), mPaint!!)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        val x = event.x
        val y = event.y

        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                if (mode === MotionMode.MOUSE_MODE) {
                    mX = x
                    mY = y
                    mXoffset = 0.0f
                    mYoffset = 0.0f
                    touchPoint(x, y)
                    startSampling()
//                    pollingHandler.postDelayed(pollingRunnber, 1000);
                }
                invalidate() //清屏
            }
            MotionEvent.ACTION_MOVE -> {
                if (mode === MotionMode.MOUSE_MODE) {
                    mXoffset = x - mX
                    mYoffset = y - mY
                    mX = x
                    mY = y
                    touchPoint(x, y)
                }
                invalidate()
            }
            MotionEvent.ACTION_UP -> {
                if (mode === MotionMode.MOUSE_MODE) {
                    touchPoint(x, y)
                    stopSampling()
                    if (hackTouchType === TouchType.THREE_FINGER) {
                        MouseAction.upOnClick()
                        hackTouchType = TouchType.NONE
                    }
//                    pollingHandler.removeCallbacks(pollingRunnber);
                }
                invalidate()
            }
        }
        return true
    }

    companion object {

        val TAG = "HackView"
    }
}
